Java锁Synchronized,对象锁和类锁举例
Java的锁分为对象锁和类锁。
1. 当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内针对该对象的操作只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
2. 然而,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
3. 尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对该object中所有其它synchronized(this)同步代码块的访问将被阻塞。
4. 同步加锁的是对象,而不是代码。因此,如果你的类中有一个同步方法,这个方法可以被两个不同的线程同时执行,只要每个线程自己创建一个的该类的实例即可。
5. 不同的对象实例的synchronized方法是不相干扰的。也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法。
6. synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法。
7.对一个全局静态对象或者类加锁时,对该类的所有对象都起作用。
类锁举例
对一个全局变量加锁:
1 public class MySynchronized extends Thread 2 { 3 private int val; 4 5 private static Object lock = new Object(); 6 7 public MySynchronized(int v) 8 { 9 val = v; 10 } 11 12 public void printVal(int v) 13 { 14 synchronized (lock) 15 { 16 while (true) 17 { 18 System.out.println(v); 19 } 20 } 21 } 22 23 public void run() 24 { 25 printVal(val); 26 } 27 }
对整个类加锁:
1 public class MySynchronized extends Thread 2 { 3 private int val; 4 5 public MySynchronized(int v) 6 { 7 val = v; 8 } 9 10 public void printVal(int v) 11 { 12 synchronized (MySynchronized.class) 13 { 14 while (true) 15 { 16 System.out.println(v); 17 } 18 } 19 } 20 21 public void run() 22 { 23 printVal(val); 24 } 25 }
另外的锁例子:
String常量的特殊性,属于同一个对象。
public class MySynchronized extends Thread { private String name; private String val; public MySynchronized(String name, String v) { this.name = name; val = v; } public void printVal() { synchronized (val) { while (true) { System.out.println(name + val); } } } public void run() { printVal(); } public static void main(String args[]) { MySynchronized f1 = new MySynchronized("Foo 1:", "printVal"); f1.start(); MySynchronized f2 = new MySynchronized("Foo 2:", "printVal"); f2.start(); } }
总结:synchronized作用于静态方法和非静态方法的区别:
/* * 非静态方法: * 给对象加锁(可以理解为给这个对象的内存上锁,注意 只是这块内存,其他同类对象都会有各自的内存锁),这时候 * 在其他一个以上线程中执行该对象的这个同步方法(注意:是该对象)就会产生互斥 * 静态方法: * 相当于在类上加锁(*.class 位于代码区,静态方法位于静态区域,这个类产生的对象公用这个静态方法,所以这块 * 内存,N个对象来竞争), 这时候,只要是这个类产生的对象,在调用这个静态方法时都会产生互斥 */